package org.gowk.sevenzip;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.List;


/**
 * <p>SevenZip class.</p>
 *
 * @author user1
 * @version $Id: $Id
 */
public class SevenZip {
    static String charset="utf8";
    /**
     * <p>getBinPath.</p>
     *
     * @return a {@link java.lang.String} object.
     * @throws java.io.IOException if any.
     */
    public static String getBinPath() throws IOException {
        String strOS = System.getProperty("os.name").toLowerCase();
        String binDir = System.getProperty("java.io.tmpdir") + "/7zbin/";
        new File(binDir).mkdirs();

        String binPath = "";
        if (strOS.indexOf("win") != -1) {
            charset="gbk";
            File bin = new File(binDir + "7za.exe");
            if (!bin.exists()) {
                Files.copy(SevenZip.class.getResourceAsStream("/bin/win/7za.exe"), bin.toPath());
            }
            binPath = bin.getAbsolutePath();
        }
        if (strOS.indexOf("linux") != -1) {
            charset="utf8";
            String[] files = { "7z.so","7z"};//主执行文件放最后
            for(String file:files){
                File bin = new File(binDir + file);
                if (!bin.exists()) {
                    Files.copy(SevenZip.class.getResourceAsStream("/bin/linux/"+file), bin.toPath());
                    if(!bin.canExecute()){
                        bin.setExecutable(true);
                    }
                }
                binPath = bin.getAbsolutePath();
            }
        }
        return binPath;
    }

    /**
     * <p>compress.</p>
     *
     * @param archiveName a {@link java.lang.String} object.
     * @param fileName a {@link java.lang.String} object.
     * @param options a {@link java.lang.String} object.
     * @return a boolean.
     */
    public static boolean compress(String archiveName, String fileName, String... options){
        boolean ok = false;
        try {
            File archiveFile=new File(archiveName);
            if(archiveFile.exists()){
                archiveFile.delete();
            }

            List<String> commend = new java.util.ArrayList<String>();
            commend.add(getBinPath());
            commend.add("a");
            commend.add("-y");
            commend.add(archiveName);
            commend.add(fileName);
            for (String option : options) {
                commend.add(option);
            }

            ProcessBuilder builder = new ProcessBuilder();
            System.out.println(commend);
            builder.command(commend);
            builder.redirectErrorStream(true);
            Process p = builder.start();
            p.getOutputStream().close();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName(charset)));
            String tmp = null;
            StringBuffer sb = new StringBuffer();
            while ((tmp = br.readLine()) != null) {
                sb.append(tmp);
            }
            int exitValue = p.waitFor();
            System.out.println(sb);
            if (sb.toString().indexOf("Everything is Ok") != -1) {
                ok = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ok;
    }

    /**
     * <p>decompress.</p>
     *
     * @param archiveName a {@link java.lang.String} object.
     * @param outputDir a {@link java.lang.String} object.
     * @param options a {@link java.lang.String} object.
     * @return a boolean.
     */
    public static boolean decompress(String archiveName, String outputDir, String... options){
        boolean ok = false;
        try {
            new File(outputDir).mkdirs();

            List<String> commend = new java.util.ArrayList<String>();
            commend.add(getBinPath());
            commend.add("x");
            commend.add("-y");
            commend.add(archiveName);
            commend.add("-o" + outputDir);
            for (String option : options) {
                commend.add(option);
            }

            ProcessBuilder builder = new ProcessBuilder();
            System.out.println(commend);
            builder.command(commend);
            builder.redirectErrorStream(true);
            Process p = builder.start();
            p.getOutputStream().close();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("utf8")));
            String tmp = null;
            StringBuffer sb = new StringBuffer();
            while ((tmp = br.readLine()) != null) {
                sb.append(tmp);
            }
            int exitValue = p.waitFor();
            //System.out.println(sb.toString());
            if (sb.toString().indexOf("Everything is Ok") != -1) {
                ok = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ok;
    }

    public static boolean isEncrypted(String archiveName){
        boolean ok = false;
        try {
            List<String> commend = new java.util.ArrayList<String>();
            commend.add(getBinPath());
            commend.add("l");
            commend.add("-slt");
            commend.add(archiveName);

            ProcessBuilder builder = new ProcessBuilder();
            System.out.println(commend);
            builder.command(commend);
            builder.redirectErrorStream(true);
            Process p = builder.start();
            p.getOutputStream().close();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("utf8")));
            String tmp = null;
            StringBuffer sb = new StringBuffer();
            while ((tmp = br.readLine()) != null) {
                sb.append(tmp);
            }
            int exitValue = p.waitFor();
            System.out.println(sb.toString());
            if (sb.toString().indexOf("Can not open encrypted archive") != -1) {
                ok = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ok;
    }

    /**
     * <p>main.</p>
     *
     * @param args an array of {@link java.lang.String} objects.
     * @throws java.io.IOException if any.
     */
    public static void main(String[] args) throws IOException {
        boolean compress = compress("e:/test.7z", "e:/test.txt",  "-pa","-mhe=on");
        System.out.println(compress);
        boolean isEncrypted = isEncrypted("e:/test.7z" );
        System.out.println(isEncrypted);
        boolean decompress = decompress("e:/test.7z", "e:/test2", "-pa");
        System.out.println(decompress);
    }
}
